"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createWorker = createWorker;
exports.createTimeoutPromise = createTimeoutPromise;
exports.blobToArrayBuffer = blobToArrayBuffer;
exports.pmToPromiseWithProgress = pmToPromiseWithProgress;
exports.pmToPromise = pmToPromise;
exports.waitForWorkerIsReady = waitForWorkerIsReady;
exports.getClipCommand = getClipCommand;
exports.getTransformSelfCommand = getTransformSelfCommand;
exports.getConvertCommand = getConvertCommand;
exports.getClipConvertCommand = getClipConvertCommand;
exports.getCombineCommand = getCombineCommand;
exports.audioBufferToBlob = audioBufferToBlob;
exports.blobToAudio = blobToAudio;
exports.audioToBlob = audioToBlob;
exports.audioToArrayBuffer = audioToArrayBuffer;
exports.timeout = timeout;
exports.isAudio = isAudio;
exports.setMediaType = setMediaType;
exports.getMediaType = getMediaType;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _types = require("./types");

var _axios = _interopRequireDefault(require("axios"));

var _lodash = require("lodash");

function createWorker(workerPath) {
  var worker = new Worker(workerPath);
  return worker;
}

function createTimeoutPromise(time) {
  return new Promise(function (resolve) {
    return setTimeout(function () {
      resolve();
    }, time);
  });
}

function blobToArrayBuffer(blob) {
  return new Promise(function (resolve, reject) {
    var fileReader = new FileReader();

    fileReader.onload = function () {
      resolve(fileReader.result);
    };

    fileReader.onerror = function (evt) {
      var err1 = (0, _lodash.get)(evt, 'target.error.code', 'NO CODE');
      var err2 = (0, _lodash.get)(fileReader, 'error.code', 'NO CODE');
      reject("fileReader read blob error: ".concat(err1, " or ").concat(err2));
    };

    fileReader.readAsArrayBuffer(blob);
  });
}

function pmToPromiseWithProgress(worker, postInfo, progressCallback) {
  var duration;
  var currentTime = 0;
  var durationReg = /Duration: (.+), start/;
  var currentTimeReg = /time=(.+) bitrate/;
  var result = {
    buffer: null,
    logs: []
  };
  return new Promise(function (resolve, reject) {
    var successHandler = function successHandler(event) {
      result.logs.push((0, _lodash.get)(event, 'data.data', '').toString());

      switch (event.data.type) {
        case 'stdout':
        case 'stderr':
          var msg = (0, _lodash.get)(event, 'data.data', '');

          if (durationReg.test(msg)) {
            duration = timeToMillisecond(msg.match(durationReg)[1] || '00:00:01');
          } else if (currentTimeReg.test(msg)) {
            currentTime = timeToMillisecond(msg.match(currentTimeReg)[1] || '00:00:00');
          }

          var progress = currentTime / duration || 0;
          progressCallback && progressCallback({
            progress: progress >= 0.999 ? 0.999 : progress,
            currentTime: currentTime,
            duration: duration
          });
          console.log('worker stdout: ', event.data.data);
          break;

        case 'start':
          console.log('worker receive your command and start to work:)');
          break;

        case 'done':
          progressCallback && progressCallback({
            progress: 1,
            currentTime: currentTime,
            duration: duration
          });
          worker.removeEventListener('message', successHandler);
          result.buffer = (0, _lodash.get)(event, 'data.data.MEMFS.0.data', null);
          resolve(result);
          break;

        case 'error':
          worker.removeEventListener('message', successHandler);
          reject(event.data.data);
          break;

        default:
          break;
      }
    };

    var failHandler = function failHandler(error) {
      worker.removeEventListener('error', failHandler);
      reject(error);
    };

    worker.addEventListener('message', successHandler);
    worker.addEventListener('error', failHandler);
    postInfo && worker.postMessage(postInfo);
  });
}

function pmToPromise(worker, postInfo) {
  var result = {
    buffer: null,
    logs: []
  };
  return new Promise(function (resolve, reject) {
    var successHandler = function successHandler(event) {
      result.logs.push((0, _lodash.get)(event, 'data.data', '').toString());

      switch (event.data.type) {
        case 'stdout':
          // case 'stderr':
          console.log('worker stdout: ', event.data.data);
          break;

        case 'start':
          console.log('worker receive your command and start to work:)');
          break;

        case 'done':
          worker.removeEventListener('message', successHandler);
          result.buffer = (0, _lodash.get)(event, 'data.data.MEMFS.0.data', null);
          resolve(result);
          break;

        case 'error':
          worker.removeEventListener('message', successHandler);
          reject(event.data.data);
          break;

        default:
          break;
      }
    };

    var failHandler = function failHandler(error) {
      worker.removeEventListener('error', failHandler);
      reject(error);
    };

    worker.addEventListener('message', successHandler);
    worker.addEventListener('error', failHandler);
    postInfo && worker.postMessage(postInfo);
  });
}

function waitForWorkerIsReady(worker, onSuccess, onFail) {
  return new Promise(function (resolve, reject) {
    var handleReady = function handleReady(event) {
      if (event.data.type === 'ready') {
        worker.removeEventListener('message', handleReady);
        onSuccess && onSuccess();
        resolve();
      }
    };

    var handleError = function handleError(err) {
      worker.removeEventListener('error', handleError);
      onFail && onFail(err);
      reject(err);
    };

    worker.addEventListener('message', handleReady);
    worker.addEventListener('error', handleError);
  });
}

function getClipCommand(arrayBuffer, st, et) {
  var type = getMediaType();
  return {
    type: 'run',
    arguments: "-ss ".concat(st, " -i input.").concat(type, " ").concat(et ? "-t ".concat(et, " ") : '', "-acodec copy output.").concat(type).split(' '),
    MEMFS: [{
      data: new Uint8Array(arrayBuffer),
      name: "input.".concat(type)
    }]
  };
}

function getTransformSelfCommand(arrayBuffer) {
  var type = getMediaType();
  return {
    type: 'run',
    arguments: "-i input.".concat(type, " -vcodec copy -acodec copy output.").concat(type).split(' '),
    MEMFS: [{
      data: new Uint8Array(arrayBuffer),
      name: "input.".concat(type)
    }]
  };
}

function getConvertCommand(arrayBuffer, originType) {
  var type = getMediaType();
  return {
    type: 'run',
    arguments: "-i input.".concat(originType, " -vn -y output.").concat(type).split(' '),
    MEMFS: [{
      data: new Uint8Array(arrayBuffer),
      name: "input.".concat(originType)
    }]
  };
}

function getClipConvertCommand(arrayBuffer, originType, st, et) {
  var type = getMediaType();
  return {
    type: 'run',
    arguments: "-ss ".concat(st, " -i input.").concat(originType, " ").concat(et ? "-t ".concat(et, " ") : '', "-y output.").concat(type).split(' '),
    MEMFS: [{
      data: new Uint8Array(arrayBuffer),
      name: "input.".concat(originType)
    }]
  };
}

function getCombineCommand(_x) {
  return _getCombineCommand.apply(this, arguments);
}

function _getCombineCommand() {
  _getCombineCommand = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(audioBuffers) {
    var type, files, txtContent, txtBlob, fileArrayBuffer;
    return _regenerator["default"].wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            type = getMediaType();
            files = audioBuffers.map(function (arrayBuffer, index) {
              return {
                data: new Uint8Array(arrayBuffer),
                name: "input".concat(index, ".").concat(type)
              };
            });
            txtContent = [files.map(function (f) {
              return "file '".concat(f.name, "'");
            }).join('\n')];
            txtBlob = new Blob(txtContent, {
              type: 'text/txt'
            });
            _context.next = 6;
            return blobToArrayBuffer(txtBlob);

          case 6:
            fileArrayBuffer = _context.sent;
            files.push({
              data: new Uint8Array(fileArrayBuffer),
              name: 'filelist.txt'
            });
            return _context.abrupt("return", {
              type: 'run',
              arguments: "-f concat -i filelist.txt -c copy output.".concat(type).split(' '),
              MEMFS: files
            });

          case 9:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _getCombineCommand.apply(this, arguments);
}

function audioBufferToBlob(arrayBuffer) {
  var type = getMediaType();
  var blob = new Blob([arrayBuffer], {
    type: toBlobMediaType(type)
  });
  return blob;
}

function blobToAudio(_x2) {
  return _blobToAudio.apply(this, arguments);
}

function _blobToAudio() {
  _blobToAudio = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(blob) {
    var url;
    return _regenerator["default"].wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            url = URL.createObjectURL(blob);
            return _context2.abrupt("return", Promise.resolve(new Audio(url)));

          case 2:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2);
  }));
  return _blobToAudio.apply(this, arguments);
}

function audioToBlob(_x3) {
  return _audioToBlob.apply(this, arguments);
}

function _audioToBlob() {
  _audioToBlob = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(audio) {
    var url;
    return _regenerator["default"].wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            url = audio.src;

            if (!url) {
              _context4.next = 5;
              break;
            }

            return _context4.abrupt("return", (0, _axios["default"])({
              url: url,
              method: 'get',
              responseType: 'arraybuffer'
            }).then( /*#__PURE__*/function () {
              var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(res) {
                var arrayBuffer, contentType, file;
                return _regenerator["default"].wrap(function _callee3$(_context3) {
                  while (1) {
                    switch (_context3.prev = _context3.next) {
                      case 0:
                        arrayBuffer = res.data;
                        contentType = res.headers['content-type'];
                        file = new File([arrayBuffer], 'result', {
                          type: contentType
                        });
                        return _context3.abrupt("return", file);

                      case 4:
                      case "end":
                        return _context3.stop();
                    }
                  }
                }, _callee3);
              }));

              return function (_x5) {
                return _ref.apply(this, arguments);
              };
            }()));

          case 5:
            return _context4.abrupt("return", Promise.resolve(null));

          case 6:
          case "end":
            return _context4.stop();
        }
      }
    }, _callee4);
  }));
  return _audioToBlob.apply(this, arguments);
}

function audioToArrayBuffer(_x4) {
  return _audioToArrayBuffer.apply(this, arguments);
}

function _audioToArrayBuffer() {
  _audioToArrayBuffer = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(audio) {
    var url;
    return _regenerator["default"].wrap(function _callee6$(_context6) {
      while (1) {
        switch (_context6.prev = _context6.next) {
          case 0:
            url = audio.src;

            if (!url) {
              _context6.next = 5;
              break;
            }

            return _context6.abrupt("return", (0, _axios["default"])({
              url: url,
              method: 'get',
              responseType: 'arraybuffer'
            }).then( /*#__PURE__*/function () {
              var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(res) {
                var arrayBuffer;
                return _regenerator["default"].wrap(function _callee5$(_context5) {
                  while (1) {
                    switch (_context5.prev = _context5.next) {
                      case 0:
                        arrayBuffer = res.data;
                        return _context5.abrupt("return", arrayBuffer);

                      case 2:
                      case "end":
                        return _context5.stop();
                    }
                  }
                }, _callee5);
              }));

              return function (_x6) {
                return _ref2.apply(this, arguments);
              };
            }()));

          case 5:
            return _context6.abrupt("return", Promise.resolve(null));

          case 6:
          case "end":
            return _context6.stop();
        }
      }
    }, _callee6);
  }));
  return _audioToArrayBuffer.apply(this, arguments);
}

function timeout(time) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      return reject(new Error('timeout in audioSculptor!'));
    }, time);
  });
}
/**
 * 判断是否为一个audio对象
 * @param audio
 */


function isAudio(audio) {
  return audio && (0, _lodash.isFunction)(audio.play) && (0, _lodash.isFunction)(audio.pause) && (0, _lodash.isFunction)(audio.canPlayType);
}

var mediaType;

function setMediaType(type) {
  mediaType = type;
}

function getMediaType() {
  return mediaType;
} // "00:30:00.47"


function timeToMillisecond(time) {
  var _time$split$map = time.split(':').map(function (str) {
    return parseFloat(str);
  }),
      _time$split$map2 = (0, _slicedToArray2["default"])(_time$split$map, 3),
      hour = _time$split$map2[0],
      minute = _time$split$map2[1],
      second = _time$split$map2[2];

  var millisecond = 0;
  millisecond += second * 1000;
  millisecond += minute * 60 * 1000;
  millisecond += hour * 60 * 60 * 1000;
  return millisecond;
}

function toBlobMediaType(mediaType) {
  return _types.BlobMediaType[mediaType];
}